package com.zzy.test.emailLogin;

import com.zzy.test.service.EmailCodeUserDetailsService;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.SpringSecurityMessageSource;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.Assert;

/**
 * @author Lucas-zhang
 * @description TODO
 * @date 2022-03-19 15:27
 */
public class EmailCodeAuthenticationProvider implements AuthenticationProvider {
    protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();

    private  EmailCodeUserDetailsService emailCodeUserDetailsService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        Assert.isInstanceOf(EmailCodeAuthenticationToken.class, authentication,
                () -> this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.onlySupports",
                        "Only UsernamePasswordAuthenticationToken is supported"));
        // 此时的authentication还没认证，获取邮箱号码
        EmailCodeAuthenticationToken unAuthenticationToken = (EmailCodeAuthenticationToken) authentication;
        // 做校验
        UserDetails user = this.emailCodeUserDetailsService.loadUserByEmail(unAuthenticationToken);
        if (user == null) {
            throw new InternalAuthenticationServiceException("EmailCodeUserDetailsService returned null, which is an interface contract violation");
        }
        System.out.println("authentication successful!");

        Object principalToReturn = user;
        return createSuccessAuthentication(principalToReturn, authentication, user);
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return EmailCodeAuthenticationToken.class.isAssignableFrom(authentication);
    }

    protected Authentication createSuccessAuthentication(Object principal, Authentication authentication, UserDetails user) {
        EmailCodeAuthenticationToken result = new EmailCodeAuthenticationToken(principal,
                authentication.getCredentials(), user.getAuthorities());
        result.setDetails(authentication.getDetails());
        return result;
    }

    public void setEmailCodeUserDetailsService(EmailCodeUserDetailsService emailCodeUserDetailsService) {
        this.emailCodeUserDetailsService = emailCodeUserDetailsService;
    }
}
